package guava;

import com.google.common.collect.Maps;
import com.google.common.util.concurrent.*;
import org.junit.Test;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;

/**
 * @author xukai
 * @desc
 * @date 2016-12-03-下午 12:26
 */
public class ConcurrentUtil {

    /**
     * 通过Monitor的Guard进行条件阻塞
     */
    public class MonitorSample {
        private List<String> list = new ArrayList<String>();
        private static final int MAX_SIZE = 10;
        private Monitor monitor = new Monitor();

        private Monitor.Guard listBelowCapacity = new Monitor.Guard(monitor) {
            @Override
            public boolean isSatisfied() {
                return list.size() < MAX_SIZE;
            }
        };

        public void addToList(String item) throws InterruptedException {
            monitor.enterWhen(listBelowCapacity); //Guard(形如Condition)，不满足则阻塞，而且我们并没有在Guard进行任何通知操作
            //Monitor.enter //进入Monitor块，将阻塞其他线程知道Monitor.leave
            //Monitor.tryEnter //尝试进入Monitor块，true表示可以进入, false表示不能，并且不会一直阻塞
            //Monitor.tryEnterIf //根据条件尝试进入Monitor块
            try {
                list.add(item);
            } finally {
                monitor.leave();
            }
        }
    }

    /**
     * ListenableFuture
     */
    @Test
    public void listenableFutureTest(){
        ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(8));
        ListenableFuture<String> listenableFuture =
                executorService.submit(new Callable<String>(){
                    @Override
                    public String call() throws Exception {
                        return null;
                    }
                });
        listenableFuture.addListener(new Runnable() {
            @Override
            public void run() {
                System.out.println();
            }
        }, executorService);
    }

    /**
     * 定义一个FutureCallBack实现类
     */
    public class FutureCallbackImpl implements FutureCallback<String> {
        private StringBuilder builder = new StringBuilder();

        @Override
        public void onSuccess(String result) {
            builder.append(result).append("successfully");
        }

        @Override
        public void onFailure(Throwable t) {
            builder.append(t.toString());
        }

        public String getCallbackResult() {
            return builder.toString();
        }
    }

    @Test
    public void CallBackFutureTest() throws ExecutionException, InterruptedException {
        ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
        ListenableFuture<String> futureTask = executorService.submit(new Callable<String>() { //创建ListenaleFuture对象
            @Override
            public String call() throws Exception {
                Thread.sleep(5000);
                return "Task completed";
            }
        });
        ListenableFuture<String> futureTask2 = executorService.submit(new Callable<String>() { //创建ListenaleFuture对象
            @Override
            public String call() throws Exception {
                Thread.sleep(1000);
                int i = 4/0;
                return "Task completed222";
            }
        });
        FutureCallbackImpl callback = new FutureCallbackImpl();
        Futures.addCallback(futureTask, callback,Executors.newFixedThreadPool(5)); //添加回调
        Futures.addCallback(futureTask2, callback,Executors.newFixedThreadPool(5)); //添加回调


        ListenableFuture<List<String>> future = Futures.successfulAsList(futureTask, futureTask2);
        System.out.println(callback.getCallbackResult()); //获取结果
        while(!future.isDone()){
            Thread.sleep(200);
            System.out.println("等待...");
        }
        System.out.println(callback.getCallbackResult());
//        ListenableFuture<Person> lf = Futures.transform(ListenableFuture<String> f,AsyncFunction<String,Person> af);
//        ListenableFuture<String> lf2 = Futures.withFallback(futureTask,new FutureFallbackImpl());
    }

    /**
     * SettableFuture
     */

    public class AsyncFuntionSample implements AsyncFunction<Long, String> {
        private ConcurrentMap<Long, String> map = Maps.newConcurrentMap();
        private ListeningExecutorService listeningExecutorService;

        @Override
        public ListenableFuture<String> apply(final Long input) throws Exception {
            if (map.containsKey(input)) {
                SettableFuture<String> listenableFuture = SettableFuture.create(); //构建一个SettableFuture
                listenableFuture.set(map.get(input));
                return listenableFuture;
            } else {
                return listeningExecutorService.submit(new Callable<String>() {
                    @Override
                    public String call() throws Exception {
                        String retrieved = "compute to get the data";
                                map.putIfAbsent(input, retrieved);
                        return retrieved;
                    }
                });
            }
        }
    }

    /**
     * 当Future任务失败后, 作为备份的Future
     */
    public class FutureFallbackImpl implements FutureFallback<String> {
        @Override
        public ListenableFuture<String> create(Throwable t) throws Exception {
            if (t instanceof FileNotFoundException) {
                SettableFuture<String> settableFuture = SettableFuture.create();
                settableFuture.set("Not Found");
                return settableFuture;
            }
            throw new Exception(t);
        }
    }

    /**
     * RateLimiter
     */
    @Test
    public void RaleLimiterTest(){
        RateLimiter limiter = RateLimiter.create(4.0); //每秒不超过4个任务被提交

        if(limiter.tryAcquire()){ //未请求到limiter则立即返回false
//            doSomething();
        }else{
//            doSomethingElse();
        }
    }


}
